/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { TypeNode, SyntaxKind } from 'ts-morph';
import { ITypeHandler, TypeContext } from './ITypeHandler';
import { PropertyKind, TypeStructure, Logger } from '..';
import { CustomError, ErrorCodes } from '../utils/CustomError';

export class TypeHandlerRegistry {
  private static instance: TypeHandlerRegistry;

  /** 所有已注册的处理器（按注册顺序） */
  private handlers: ITypeHandler[] = [];

  /** Kind到Handler的快速查找表 */
  private kindMap: Map<PropertyKind, ITypeHandler> = new Map();

  /** 类型名称到Handler的快速查找表（支持多个候选） */
  private nameMap: Map<string, ITypeHandler[]> = new Map();

  private constructor() { }

  /**
   * 获取单例实例
   */
  static getInstance(): TypeHandlerRegistry {
    if (!TypeHandlerRegistry.instance) {
      TypeHandlerRegistry.instance = new TypeHandlerRegistry();
    }
    return TypeHandlerRegistry.instance;
  }

  // ==================== 注册管理 ====================

  /**
   * 注册类型处理器
   * @param handler 类型处理器实例
   */
  register(handler: ITypeHandler): void {
    // 添加到列表
    this.handlers.push(handler);

    // 按优先级排序（优先级高的在前）
    this.handlers.sort((a, b) => b.priority - a.priority);

    // 更新Kind映射（只保留最高优先级）
    const existingHandler = this.kindMap.get(handler.kind);
    if (!existingHandler || handler.priority > existingHandler.priority) {
      this.kindMap.set(handler.kind, handler);
    }

    // 更新类型名称映射（支持多个候选）
    const typeName = this.extractTypeName(handler.kind);
    const candidates = this.nameMap.get(typeName) || [];
    candidates.push(handler);
    candidates.sort((a, b) => b.priority - a.priority);
    this.nameMap.set(typeName, candidates);
  }

  /**
   * 批量注册处理器
   * @param handlers 处理器数组
   */
  registerAll(handlers: ITypeHandler[]): void {
    handlers.forEach((handler) => this.register(handler));
  }

  // ==================== 处理器查找 ====================

  /**
   * 根据PropertyKind查找处理器
   * @param kind PropertyKind
   * @returns 对应的处理器，如果不存在返回undefined
   */
  getHandlerForKind(kind: PropertyKind): ITypeHandler {
    const handler = this.kindMap.get(kind);
    if (!handler) {
      // 理论上走不到这里来
      throw new CustomError(`No handler for kind: ${kind}`, ErrorCodes.HANDLER_NOT_FOUND);
    }
    return handler;
  }

  /**
   * 根据类型节点查找匹配的处理器
   * @param typeNode AST类型节点
   * @param context 上下文
   * @returns 匹配的处理器，如果没有匹配返回undefined
   */
  findHandler(typeNode: TypeNode, context: TypeContext): ITypeHandler | undefined {
    const typeName = typeNode.getText();

    // 策略1: 先尝试类型名称精确匹配
    const candidates = this.nameMap.get(this.normalizeTypeName(typeName));
    if (candidates && candidates.length > 0) {
      for (const handler of candidates) {
        if (handler.matches(typeNode, context)) {
          return handler;
        }
      }
    }

    // 策略2: 遍历所有处理器（按优先级顺序）
    for (const handler of this.handlers) {
      if (handler.matches(typeNode, context)) {
        return handler;
      }
    }

    Logger.warn(`No handler found for type: ${typeName}`);
    return undefined;
  }

  // ==================== 类型解析入口 ====================

  /**
   * 解析类型节点为类型结构
   * @param typeNode AST类型节点
   * @param context 类型上下文
   * @returns 类型结构
   */
  parseType(typeNode: TypeNode, context: TypeContext): TypeStructure {

    // 字面量类型检测：除了 null 和 undefined，其他字面量类型都不支持
    if (typeNode.getKind() === SyntaxKind.LiteralType) {
      const literal = typeNode.asKindOrThrow(SyntaxKind.LiteralType);
      const literalValue = literal.getLiteral();
      const literalKind = literalValue.getKind();

      // 允许 null 和 undefined 字面量
      if (literalKind !== SyntaxKind.NullKeyword && literalKind !== SyntaxKind.UndefinedKeyword) {
        throw new CustomError(
          `不支持字面量类型 '${typeNode.getText()}'（无论出现在何处）。\n` +
          `不支持的字面量类型包括：字符串字面量（如 'admin'）、数字字面量（如 123）、布尔字面量（如 true）。\n` +
          `即使在联合类型、Type 别名、泛型参数中使用字面量也不支持。\n` +
          `请使用基础类型：string、number、boolean 替代字面量类型。`,
          ErrorCodes.LITERAL_NOT_SOPPORT);
      }
    }

    // 处理 ParenthesizedType (括号类型)例如 (string|number)
    if (typeNode.getKind() === SyntaxKind.ParenthesizedType) {
      // 对于括号类型，我们解析其内部的类型
      const parenthesizedType = typeNode.asKindOrThrow(SyntaxKind.ParenthesizedType);
      const innerTypeNode = parenthesizedType.getTypeNode();

      // 递归解析括号内的类型
      return this.parseType(innerTypeNode, context);
    }

    const handler = this.findHandler(typeNode, context);
    if (!handler) {
      // 容错机制：找不到处理器时返回 UNKNOWN 类型
      // ClassAnalyzer 会检查是否有 @Transient 注解来决定如何处理
      const typeName = typeNode.getText();
      Logger.warn(`No handler found for type: ${typeName}, marking as UNKNOWN`);

      return {
        kind: PropertyKind.UNKNOWN,
        depth: 0,
        sourceText: typeName,
        args: [],
        dependencies: []
      };
    }

    return handler.parse(typeNode, context);
  }

  // ==================== 代码生成入口 ====================

  /**
   * 生成序列化器实例化代码
   * @param structure 类型结构
   * @returns 实例化代码字符串
   */
  generateInstantiation(structure: TypeStructure): string {
    const handler = this.getHandlerForKind(structure.kind);

    return handler.generateInstantiation(structure);
  }

  generateTypeKey(structure: TypeStructure): string {
    const handler = this.getHandlerForKind(structure.kind);

    return handler.generateTypeKey(structure);
  }

  // ==================== 辅助方法 ====================

  /**
   * 从PropertyKind提取类型名称
   * @param kind PropertyKind
   * @returns 类型名称
   * @example 'string' -> 'string', 'array' -> 'Array', 'collections.Array' -> 'Array'
   */
  private extractTypeName(kind: PropertyKind): string {
    // 处理collections.*类型
    if (kind.startsWith('collections.')) {
      return kind.split('.')[1];
    }

    // 基础类型直接返回
    return kind;
  }

  /**
   * 规范化类型名称（用于查找）
   * @param typeName 原始类型名称
   * @returns 规范化后的名称
   * @example 'Array<string>' -> 'Array', 'collections.Array<T>' -> 'Array'
   */
  private normalizeTypeName(typeName: string): string {
    // 移除泛型参数
    const withoutGenerics = typeName.split('<')[0].trim();

    // 处理collections.*
    if (withoutGenerics.startsWith('collections.')) {
      return withoutGenerics.split('.')[1];
    }

    return withoutGenerics;
  }
}